home *** CD-ROM | disk | FTP | other *** search
Text File | 1988-12-01 | 84.5 KB | 3,659 lines |
-
-
-
-
- Memory Management Extensions
- to the SRI Micro Operating System
- for PDP-11/23/34/35/40
-
-
-
-
-
-
-
-
-
-
- IEN 136
-
- 1st MAY 1980
-
-
-
-
-
-
-
-
-
- S.R. Wiseman
- B.H. Davies
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ROYAL SIGNALS & RADAR ESTABLISHMENT
- North Site, Leigh Sinton Rd., Malvern, Worcs., UK.
-
- 1
-
-
-
- CONTENTS
- ________
-
- 0. Introduction
-
- PART 1 - SYSTEM DESIGN
-
- 1. Requirement
-
- 1.2 Overview of solution
-
- 1.3 Use of Memory Management Facility
-
-
- PART 2 - TARGET MACHINE ASPECTS
-
- 2.1 Alterations to MOS
- 2.1.1 The Process Control Table
- 2.1.2 The Scheduler
- 2.1.3 The $CREAP Macro
- 2.1.4 Input and Output Routines
- 2.1.5 Memory Sizing
- 2.1.6 Protection Routines
- 2.1.7 System Configuration
-
- 2.2 The EMMOS Debugger - MUD
- 2.2.1 A Summary of MUD Commands
- 2.2.2 MUD Command Syntax
- 2.2.3 The Relocation Mechanism
- 2.2.4 Addressing Modes
- 2.2.5 Command Specifications
- 2.2.6 Using MUD
-
- 2.3 Linker and Loader Functions
- 2.3.1 The Linker
- 2.3.2 The Loader
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 2
-
- PART 3 - HOST MACHINE ASPECTS
-
- 3.1 Linking Using the RSX-11M Task Builder
- 3.1.1 Use of the Task Builder's Task Image File
- 3.1.2 The Format of the Task Image File
- 3.1.3 The Overlay Description Language
- 3.1.4 The EMMOS ODL File
- 3.1.5 Installation of the Debugger
- 3.1.6 Creating the Task Image File
-
- 3.2 The EMMOS RSX Task Image Loader
- 3.2.1 Inputs and Outputs
- 3.2.2 The Console Load Map
- 3.2.3 The Configuration Table
- 3.2.4 The Overlay Description Table
- 3.2.5 The Process Description Table
- 3.2.6 The Load Map
- 3.2.7 The Physical Memory Allocation Algorithm
- 3.2.8 The Logical Operation of the Loader
- 3.2.9 Error Messages
- 3.2.10 Tracing
- 3.2.11 Changing the System
-
- 3.3 Process Creation
-
-
-
-
-
- Appendix A: Pitfalls and How to Avoid Them
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 3
-
-
-
- 0. Introduction
- ____________________
-
- This document describes the requirement, design and implementation
- of memory management extensions to the Stanford Research Insitute's
- Micro Operating System (MOS) for PDP-11 minicomputers. The document is
- divided into three parts. Part 1 covers the rationale behind the way in
- which the memory management facility of the PDP-11 is used. The results
- of the work fall naturally into Parts 2 and 3. Part 2 describes the
- modifications to MOS itself and the debugger which are independent of
- the operating system of the host machine on which the target system is
- generated. Part 3 describes the Linking and Loading modules which are
- dependent on the operating system of the host machine. The host machines
- used at RSRE are PDP -11/34 and 40s running RSX-11M v3.2. Also we have
- provision in our standard MOS for writing processes in a high level
- language, CORAL 66, which requires the use of an auxiliary stack pointed
- to by R0. This facility may be excluded from the extended MOS by the use
- of a configuration switch.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 4
-
-
-
-
-
-
-
-
-
-
-
-
-
- PART ONE
- ________
-
- SYSTEM DESIGN
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 5
-
- 1.1 Requirement
- ___________________
-
- For a number of planned real-time software projects the 28k words
- of code and data space accessible without memory management in the
- PDP-11 is inadequate. Therefore the question arises is it possible to
- use the memory management registers to provide more code and/or data
- space up to 124k words, with minimal overheads in the form of context
- switching and with no modifications to presently written processes?
-
-
- 1.2 Overview of Solution
- ____________________________
-
-
- The reason for the provision of a two state memory management
- system in the PDP-11s is not only to allow access to memory above 28k
- words but also, by the use of kernel and user modes, to provide
- protection between processes and the core resident part of the operating
- system. This usually means that the I/O page is non-resident when a user
- process is running and that I/O is handled in kernel mode. Thus in a
- real-time system there may be unacceptable overheads due to the
- considerable amount of context switching involved in this protection
- mechanism. However if one is willing to dispense with interprocess and
- operating system protection a simple and elegant solution which produces
- no detectable overheads is possible.
-
- The basic concept of the solution is that while a process is
- running there is no need to have in scope any other process so that a
- snapshot of the 32k virtual memory at any one time will look like an
- ordinary MOS system configured for one process. The only extra
- executable code involved is in the scheduler for paging out the process
- that has just finished running and paging in the process that is about
- to be run. The I/O page, operating system, handlers and common buffer
- area are always resident otherwise access to these entities would have
- to be mediated by the operating system so that they could be paged in
- with consequent increase in overheads. A typical MOS process runs for
- something like 1 millisecond and the additional paging overhead is 4 MOV
- instructions taking about 20 micro seconds, a 2% overhead. A major
- change in the MOS layout occurs in the positioning of the stacks.
- Because we want the permanently resident part of MOS to be as small as
- possible and never greater than 8k words the stacks have been removed
- from the Process Control Tables and are paged in and out with their
- processes.
-
-
- 1.3 Use of the Memory Mangement Facility
- ____________________________________________
-
- At any one time only the running process will reside in virtual
- memory, the others will be suspended and so have no need to be
- accessible. Permanently resident in virtual memory will be the vector
- area, global buffer area, operating system including all handlers, and
- the I/O page. Because the maximum size of a page is 4K words and it's
- position is fixed in virtual memory, the allocation of these pages is
- somewhat restricted. However a trade-off between global buffer space,
-
- 6
-
- operating system size and process space is possible to some extent, and
- the following configurable options are catered for:-
-
-
- Options where code and stack space of any process does not exceed 4k words:-
-
-
- Option 1
- ________
-
- 20k words of buffer space
- <4k of operating system and handlers
-
-
- |-----------------------| 32k
- 7 | I/O |
- |-----------------------| 28k
- 6 |Running process & stack|
- |-----------------------| 24k
- 5 | Operating System EMMOS|
- |-----------------------| 20k
- 4 | Global Buffers |
- |- -| 16k
- 3 | |
- |- -| 12k
- 2 | |
- |- -| 8k
- 1 | |
- |- -| 4k
- 0 | |
- page |-----------------------| 0k
-
- Option 2
- ________
-
- 16k words of buffers
- <8k operating system and handlers
- |-----------------------| 32k
- 7 | I/O |
- |-----------------------| 28k
- 6 |Running process & stack|
- |-----------------------| 24k
- 5 | Operating System EMMOS|
- |- -| 20k
- 4 | |
- |-----------------------| 16k
- 3 | Global buffers |
- |- -| 12k
- 2 | |
- |- -| 8k
- 1 | |
- |- -| 4k
- 0 | |
- page |-----------------------| 0k
-
-
-
- 7
-
-
- Options where code and stack space of any process does not exceed 8K words:-
-
- Option 3
- ________
-
- 16k words of buffer space
- < 4k words of operating system and handlers
-
- |-----------------------| 32k
- 7 | I/O |
- |-----------------------| 28k
- 6 |Running process & stack|
- |- -| 24k
- 5 | |
- |-----------------------| 20k
- 4 | Operating System EMMOS|
- |-----------------------| 16k
- 3 | Global Buffers |
- |- -| 12k
- 2 | |
- |- -| 8k
- 1 | |
- |- -| 4k
- 0 | |
- page |-----------------------| 0k
-
- Option 4
- ________
-
- 12k words of buffers
- <8k words for operating system and handlers
-
- |-----------------------| 32k
- 7 | I/O |
- |-----------------------| 28k
- 6 |Running process & stack|
- |- -| 24k
- 5 | |
- |-----------------------| 20k
- 4 | Operating System EMMOS|
- |- -| 16k
- 3 | |
- |-----------------------| 12k
- 2 | Global Buffers |
- |- -| 8k
- 1 | |
- |- -| 4k
- 0 | |
- page |-----------------------| 0k
-
-
-
-
-
-
-
- 8
-
- Only kernel mode is used by EMMOS, even user processes run in
- kernel mode because no attempt has been made to produce a secure system.
- However with options 3 and 4 the process space and stack space are
- allocated separate pages wherever possible. Thus the debugger or a
- procedure call may be used to write-protect the code space if desired.
- Holes appear in virtual memory from the end of the code or stack to the
- end of the 4k boundary ensuring that a system stack cannot underflow and
- the running process cannot access another process' code or stack .
- However, a process can damage another process indirectly by, for
- example, supplying a pointer to data on its stack to another process.
-
- Because the debugger is bigger than 4k, options 1 and 2 do not
- allow use of the debugger. This is not a serious drawback as it is
- envisaged that debugging could take place with options 3 or 4 and that
- options 1 or 2 could then be used to give another 4k words of buffer
- space.
-
- Using EMMOS requires a stricter discipline when writing processes
- than was required with MOS. Strictly speaking the code of a process
- should not contain any private data space. If a process wants private
- data space it should use its stack. Any data space shich is shared by
- two or more processes should be obtained , via MOSMEM calls, from the
- global buffer area. Exceptionally a single incarnation of an assembler
- process could reserve space after its code for local tables but any
- attempt by another process to access this area will result in disaster!
- All high level language processes should be written as closed procedures
- with private data area on their stacks.
-
- Shared Library procedures must either be replicated so that they
- are paged in with each process that requires to use them or they must be
- linked with the EMMOS operating system so that they are permanently
- resident
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 9
-
- A typical example of real and virtual memory allocations for
- an EMMOS system are shown below:-
- 128k |-----------------------|
- | I/O addresses |
- 124k |-----------------------|
-
- | |
-
- | |
- | |
- |-----------------------|
- | stack (proc3) |
- |-----------------------|
- | stack (proc2) |
- |-----------------------| 32k |_______________________|
- 7 | I/O | | Codebody2 (proc 2&3) |
- |-----------------------| 28k |_______________________|
- 6 |Running process & stack| | stack (proc1) |
- |- -| 24k |_______________________|
- 5 | | | Codebody1 (proc1) |
- |-----------------------| 20k |-----------------------|
- 4 | Operating System EMMOS| | Operating System EMMOS|
- |- -| 16k |- -|
- 3 | | | |
- |-----------------------| 12k |-----------------------|
- 2 | Global Buffers | | GLOBAL buffers |
- |- -| 8k |- -|
- 1 | | | |
- |- -| 4k |- -|
- 0 | | | |
- |-----------------------| 0k |-----------------------|
- Page Virtual Memory Physical Memory
-
-
-
-
- The linker/loader system used with EMMOS should be reasonably
- intelligent! It is it's job to reserve physical memory in accordance
- with the stack size requested for each process. In particular it must
- evaluate the total memory requirements of a process that has more than
- one incarnation and determine whether or not some or all of the code has
- to be replicated.This may arise when the stacks of all the incarnations
- of a process plus the code will not fit into the paging window. The
- linker/loader is also responsible for outputting error messages when the
- process and stack requirements cannot be satisfied by that particular
- configuration of EMMOS.
-
-
-
-
-
-
-
-
-
-
-
- 10
-
-
-
-
-
-
-
-
-
-
- PART TWO
- ________
-
- TARGET MACHINE ASPECTS
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 11
-
- 2.1 Alterations to MOS
- ___________________________
-
- Perhaps the most vital alteration is that made to the scheduler. A
- context swap now involves saving the suspended process' window and
- restoring the new process' window. This however, only involves about
- four move instructions extra, for a typical configuration ( 8K processes
- ).
-
- The major alteration is, however, to the Process Control Tables (
- PCTs ) and consequently to the PCT initializer. In particular the stacks
- for a process no longer reside here, hence a process' PCT is relatively
- small. Extra fields in the PCTs give the memory management window
- necessary to 'page-in' the process and the ends of the system and CORAL
- stacks. The PCT initializer now has to cope with setting up these
- fields, which it does by consulting the load map, supplied by the
- linker/loader.
-
- Additions have also been made to the $CREAP macro. The sizes of the
- system and CORAL stacks are given to the $CREAP which in turn passes the
- information to the linker/loader ( depending on the method used ).
-
- It has also been necessary to offer modified synchronous I/O
- routines 'SOUT' and 'SIN'. The original versions can be used if the I/O
- is performed on buffers from the permanently resident buffer pool,
- however they will not work if the I/O buffer is taken from the local
- code or data space. This is because the local area may be paged-out when
- the interrupt routine tries to get the next character, causing it to
- pick up rubbish or trap out. The new versions will copy the local I/O
- buffer into a global buffer before initiating the I/O, thus ensuring
- that it is always paged-in. This is likely to be the main overhead of
- the system.
-
- Finally, the memory sizing performed in MOSMEM is no longer
- required. This is because the position of the global buffer pool is
- fixed by the page allocation scheme.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 12
-
- 2.1.1 The Process Control Table
-
- The following fields have been added to the PCT:
-
- pct_mmr : ARRAY [ first_page..last_page ] OF window_type;
- pct_r0e, pct_r6e : virtual_byte_addresses;
- where
- TYPE window_type = RECORD par, pdr : INTEGER END;
- TYPE virtual_byte_addresses = 0..#177777;
-
- The following field has been removed from the PCT:
-
- pct_stk : ARRAY [ 1..stk_len ] OF BYTES
-
- pct_mmr is an array containing the window required to 'page-in' the
- process. The bounds are not 0..7 because it is known that most pages
- remain constant, only pages first_page to last_page are changed since
- this is the amount of virtual memory allocated to a process. Each
- element of the array is four bytes long and contains the page address
- register ( par ) and page descriptor register ( pdr ) values for that
- page.
-
- pct_r0e and pct_r6e contain the virtual byte addresses of the ends
- ( smallest numbered address ) of the R0 ( CORAL ) and R6 ( system )
- stacks. These values are used to detect stack overflow.
-
- Since the stacks no longer reside in the PCT the field pct_stk has
- been removed.
-
- The new fields in the PCT are set up directly from the Load Map
- produced by the linker/loader.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 13
-
- 2.1.2 The Scheduler
-
- A context swap now involves saving and restoring the memory
- mapping, as well as the general register values. We can actually avoid
- saving the mapping when a process is suspended because normally it
- remains constant. The protection on a page is the only thing likely to
- change and if this is done using the supplied routines then we can still
- avoid doing the saving.
-
- When the process is made runnable it is first 'paged-in' by
- restoring it's memory mapping. To ensure that the stack pointer and it's
- stack are restored together, interrupts are disabled earlier than in the
- old version. If an interrupt is allowed to occur between 'paging-in' the
- stack and restoring the stack pointer then disaster will obviously
- follow.
-
- Stack overflow, on both the R0 ( CORAL ) and R6 ( system ) stacks,
- is checked for when the process is suspended. The ends of the stacks are
- marked with overflow detect words, the address of which is held in the
- PCT. It is a simple matter to check if these words are still intact. If
- the system has no CORAL processes or library routines then the checks
- made on the R0 stack can be omitted by setting a switch in the EMMOS
- configuration file.
-
- 2.1.3 The $CREAP Macro
-
- This macro initializes parts of the PCT, the rest is done at run
- time. Two extra parameters are now required, which specify the size, in
- words, of the R0 ( CORAL ) and R6 ( system ) stacks. To avoid confusion
- the parameters should be called by name, the default size is zero words:
-
- eg: $CREAP G802,<UX25 >,,DV.IMP+0,DV.IMP+1,R0SIZE=200,R6SIZE=20
- $CREAP G802,<UX25 >,,DV.IMP+2,DV.IMP+3,R6SIZE=30,R0SIZE=350
-
- The macro converts the size into memory blocks ( 40 octal words )
- and places the information, along with the process id and name, in the
- .PSECT LDRCON. This information is used by the linker/loader in a way
- that depends on the methods being used. Note that different incarnations
- of the same process can have different sizes of stacks. In the above
- example ( all numbers are octal ) the first process would have
-
- ceiling( 200/40 ) = 4 memory blocks = 200 words for R0
- ceiling( 20/40 ) = 1 memory block = 40 words for R6
- and the second process would have
- ceiling( 350/40 ) = 10 memory blocks = 400 words for R0
- ceiling( 30/40 ) = 1 memory block = 40 words for R6
-
- Note: "ceiling( r )" is a function that rounds up real numbers to
- the next largest integer.
-
-
-
-
-
-
-
-
- 14
-
- 2.1.4 Input and Output Routines
-
- The synchronous I/O routines, SIN and SOUT, have to be modified for
- use with EMMOS. The user interface is unchanged, but the method of
- operation is slightly different. SOUT now grabs a global buffer, copies
- the string into it from the user's buffer and then performs the SIO on
- the global buffer, to output the characters. SIN grabs a global buffer,
- calls SIO to fill it and then copies the string into the user's buffer.
-
- This is necessary because if the string to be output is in the
- process' local area, it will be 'paged-out' with the process. SIO uses a
- pointer to the string ( a virtual address ) to get the characters, so if
- it does this when the initiating process is 'paged-out', it will either
- pick up rubbish or cause a memory management error. Similarly for SIN.
-
- The copying would not be required for a string already in a global
- buffer, because the buffer will always be 'paged-in', regardless of
- which process is running. In this case the MOS versions could be renamed
- and used to avoid a loss of efficiency.
-
- The same problems apply to the asynchronous I/O routine, SIO.
- However, any copying from local data space to a global buffer that is
- needed, is left up to the user. Checks have been included in the code
- that ensure both the IORB and the data area are in the global buffer
- pool or the resident EMMOS code. These checks can be omitted for a
- program known to work by setting a switch in the EMMOS configuration
- file.
-
- 2.1.5 Memory Sizing
-
- This is now not carried out. The limits of the global buffer area
- are assumed to be the ends of the pages allocated to buffers ( less
- space for the vectors if this includes page 0 ). It is assumed that the
- hardware has been configured in a sensible manner.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 15
-
- 2.1.6 Protection Routines
-
- Two routines are supplied, one to inspect the access control field
- ( ACF ) of a page, the other to change the ACF. Under the memory
- management system each page can be either
-
- 1. non-resident -all attempts at access will cause
- a trap
- 2. read-only -attempts to write into a location
- in the page will cause a trap
- 3. (unused) -same as non-resident
- 4. read/write -neither reads nor writes are trapped
-
- The two routines will only work for one of the process pages. They
- both return an integer result. This equals 'true' if the page specified
- is a process page, else it equals 'false' and the ACF is not changed or
- inspected. The pre-defined constants, 'non resident', 'read only', 'un
- used' and 'read write', should be used to specify and compare the ACFs.
-
- INTEGER PROCEDURE change page protection ( VALUE INTEGER page, access );
-
- If the page specified is a process page then the ACF of that page
- is changed to the given access. The copy of the memory management
- registers held in the PCT table for this process, is also updated.
-
- INTEGER PROCEDURE current protection ( VALUE INTEGER page;
- LOCATION INTEGER pct, pdr );
-
- If the page specified is a process page then pct and pdr are set to
- the values of the ACF field of the memory management registers for that
- page, taken from the PCT window area and active page registers
- respectively. The two different versions are supplied in case one of
- them has been corrupted. Both should always be the same.
-
-
- CORAL Constant Values
-
- true 1
- false 0
- non resident 0
- read only 2
- un used 4
- read write 6
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 16
-
- cont.
-
- The assembler versions of these routines are completly re-entrant
- and run to completion, so it is possible to have one copy of the code in
- the resident part of the system which is shared between all processes.
- The routine to change the page protection is called $CHAPP and the
- routine to inspect the current protection is called $CURPP, they have
- the same effect as the CORAL versions but are called as follows:
-
-
-
- Change Page Protection :
- called by JSR PC,$CHAPP
- with R2 = number of the page to be changed
- R3 = the new access of that page
- returns with
- R1 = TRUE or FALSE
- R0 and R2...R6 unchanged
-
- Inspect Current Page Protection :
- called by JSR PC,$CURPP
- with R2 = number of page to be examined
- returns with
- R1 = TRUE or FALSE
- R3 = value from PCT
- R4 = value from active PDR
- R0, R5 and R6 unchanged
-
-
- Assembler Constant Values
-
- TRUE 1
- FALSE 0
- NONRES 0
- READON 2
- UNUSED 4
- RWRITE 6
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 17
-
- 2.1.7 System Configuration
-
- The page allocation scheme, operating system options and various
- buffer addresses, are specified in the configuration file, EMMSYS.SML .
-
- 2.1.7i The Page Allocation Scheme
-
- The virtual memory is divided up into 8 pages of 4K words, numbered
- 0..7. Page 7 is always allocated for the I/O page, the remaining seven
- are split between the global buffers, the operating system and the
- running process ( including it's stacks ). The order is critical,
- buffers should be at the low numbered end, then the system, then the
- process and finally the I/O page. The exact split is given by specifying
- the first and last page used by each part.
-
- eg buffers 0 - 3 emmos 4 - 5 process 6 - 6
- or buffers 0 - 2 emmos 3 - 4 process 5 - 6
-
- When decreasing the space allocated to the global buffers, be sure
- that the workspace buffers ( see 2.1.7iii ) are still located before
- EMMOS, otherwise EMMOS may be loaded on top of one of them before it's
- finished with. Note: different linking/loading schemes may lend
- themselves to a different ordering of buffers, system and process, in
- which case minor alterations to the PCT initializer may be necessary.
- The I/O page must always be page 7.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 18
-
- 2.1.7ii Operating System Options
-
-
- EMMOS: EMMOS/MOS selection switch
- = 0 for EMMOS
- = 1 for MOS ( SAVMAP and SET250 have no meaning )
-
- SAVMAP: save mapping when process suspended switch
- = 0 when a process is suspended the window is saved as part
- of the process' volatile environment. This allows a
- process to change the window dynamically ( eg the
- protection ). Note, only that part of the window for the
- pages allocated to processes is saved and restored, so
- changing other pages will affect all processes.
- = 1 the window is not saved each time the process is
- suspended. The original value is reloaded when the
- process is run again, erasing any changes made.
-
- It is recommended that SAVMAP = 1 and the supplied protection
- routines are used to change the page allocation, with the other
- fields left well alone.
-
- SET250: memory management error trap initialization on/off
- = 0 when the system is initialized the trap is set to a local
- handler.
- = 1 the trap is left untouched, this option should only be
- used when the debugger is used ( MUD will set up it's
- own handler ).
-
- COPYIO: sin/sout version selection switch
- = 0 ( OR EMMOS = 0 )
- use the versions of sin and sout that copy to/from a
- global buffer before initiating the I/O.
- = 1 ( AND EMMOS = 1 )
- the MOS versions will be used
-
- NOCORL: CORAL process indicator
- = 0 no processes are written in CORAL, or use CORAL libraries,
- so the R0 stack is not checked for overflow each time a
- process is suspended. The stack is still set up as
- usual. The R6 stack is still checked.
- = 1 There is a process using CORAL, so the R0 stack will
- be used. Both stacks are checked for overflow each
- time the process is suspended.
-
- CHKSIO: SIO buffer address checking on/off
- =0 Each time SIO is called the IORB and the data addresses
- are checked to ensure that they are in the global buffer
- pool or the resident EMMOS code. An attempt to use a
- local iorb or data area will cause a BUGHLT.
- =1 No checks are performed. The use of a local IORB or data
- area is likely to cause the system to crash.
-
-
-
-
-
- 19
-
- 2.1.7iii Workspace Buffer Addresses
-
- The linker/loader and system initializer must agree on the postion
- of the load map. It's address is given by MAPADD in the system
- configuration file. The linker/loader is given this information in some
- implementation dependant way.
-
- Note that in the RSX linker/loader system, the area specified by
- MAPADD is also used by the loader for other workspace buffers during
- load time, because of this MAPADD must specify an area of store, lying
- between the end of the loader and the beginning of where EMMOS will be
- loaded, of about
-
- 25 * max_number_of_processes ( decimal ) words long
-
- The loader ends around 032000, without removing redundant
- libraries, so even for a max number of 30 processes ( 25 * 30 decimal is
- about 1400 octal ), giving MAPADD = 32000 would mean the tables would
- end way below 040000. This allows us to load a system with only 8K of
- buffers.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 20
-
- 2.2 The EMMOS Debuggger - MUD
- __________________________________
-
- MUD (Marvellous Universal Debugger) is split into two parts, RESMUD
- and MUD proper. RESMUD is a small program written in MACRO-11 that is
- permanently resident in virtual memory. It acts as the interface between
- the operating system and the debugger, MUD, which is only brought into
- virtual memory when it is needed.
-
- MUD is loaded by the loader in the same way as any other overlay.
- Normally , however, overlays that are not $CREAPed do not have entries
- in the load map, but the loader creates a special entry for the
- debugger. RESMUD uses this entry to find out where MUD has been loaded,
- and transfers control to it. For this reason RESMUD must be the first
- module loaded, even before MOSPM, if the debugger is to be used.
-
- If RESMUD is not included in the system, then MUD will be ignored
- if it is itself included, and the debugger cannot be used. EMMOS will
- ignore MUD, unless a process is foolishly creaped with the name MUDSYS!
-
- The debugger is able to reference the whole of the 18 bit physical
- store without the user knowingly changing the memory management
- registers.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 21
-
- 2.2.1 A Summary of MUD Commands
-
- The name of a command is one or two letters long, in upper or lower
- case, as follows:
-
- Print Commands:
-
- pb print breakpoint locations
- ( see breakpoint commands )
- pr print the value of a relocation register
- ( see relocation commands )
-
- Spy Commands:
-
- s spy on store
- sr spy on the registers
- sw spy on the memory management window
-
- Breakpoint Commands:
-
- b set a breakpoint
- k kill a breakpoint
- pb print breakpoint locations
- ( see print commands )
-
- Enter User Program Commands:
-
- g go to a specific address
- gs go to a specific address single stepping
- c continue from a breakpoint
- cs continue from a breakpoint single stepping
-
- Relocation Commands:
-
- r set a relocation register
- pr print the value of a relocation register
- ( see print commands )
-
- Exit Command
-
- x leaves MUD and halts
-
- Special Commands
-
- i change I/O channel
- e evaluate an arithmetic expression
- f find a memory location containing a given value
-
-
-
-
-
-
-
-
-
-
- 22
-
- 2.2.2 MUD Command Syntax
-
- The syntax is fairly simple and is quite free with spaces. A
- command consists of the command name, one or two letters( upper or lower
- case ), optionally followed by one or two operands.
-
- <name>
- <name> <op1>
- <name> <op1> <op2>
-
- The two operands and the name may be seperated by commas or spaces.
- The operands specify 18 bit addresses or numbers in octal. Their syntax
- is:
-
- <operand> ::= <repeat symbol>
- or= <number> <relocation> <mode>
-
- <repeat symbol> ::= *
-
- <number> ::= <18 bit octal number>
- or= null
-
- <relocation> ::= . <relocation register>
- or= null
-
- <relocation register> ::= <octal digit>
- or= null
-
- <mode> ::= V
- or= P
- or= null
-
- If the octal digit is ommitted, it is assumed to be zero. If the
- relocation dot is not present, then the operand is assumed to be an
- absolute physical address. If the octal digit is missed out, then
- relocation register one is assumed. Hence the following examples all
- mean the same:
-
- s100.,150.
- s100.1 150.
- s 100. , 150.1
- s 100.1 150.1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 23
-
- 2.2.3 The Relocation Mechanism
-
- There are seven relocation registers supplied ( r1..7 ) which can
- be used to modify an address in a command. Values are put into these
- registers by the 'r' command (qv). To specify that an address is to be
- relocated it is followed by a dot and perhaps a digit. The digit is the
- name of the relocation register to be used and is one by default. When
- relocation is specified, the contents of the relocation register are
- added to the address giving the actual address used. For example:
-
- r2,100 - sets relocation register 2 to 100
- s20.2 - spys on location 20+100=120
- r350 - sets relocation register 1 to 350
- s30. - spys on location 30+350=400
-
- Many commands allow an asterisk to be used as an operand, this
- usually means 'all' in some way, for example:
-
- k100 - kill the breakpoint at location 100
- k * - kill all breakpoints
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 24
-
- 2.2.4 Addressing Modes
-
- An operand can refer to a virtual location by following the
- relocation indicator by a 'V' ( the default mode is 'P', so normally
- addresses are physical ). The corresponding physcial location will be
- computed using the user's window. Page lengths are ignored.
-
- For example, if the base address of page 5 ( virtual addresses
- 120000-137777 ) is 120100 and relocation register 2 contains 120000,
- then the following are equivalent:
-
- s120110 - physical address by default
- s120110p - physical address specified
- s120010v - pa = 010 + base(5) = 120110
- s110.2 - pa = 110 + 120000 = 120110
- s110.2p - . . . . physical specified
- s10.2v - va = 10 + 120000 = 120010
- - pa = 010 + base(5) = 120110
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 25
-
- 2.2.5 Command Specification
-
-
- pb print breakpoint locations
-
- pb prints out a list of all the breakpoints
- that are set, showing their location as an
- absolute address and as an offset +
- relocation.
-
- pr print relocation registers
-
- pr print out the value of relocation register 1
- pr 'd' print out the value of relocation register 'd'
- pr * print out the value of all the relocation
- registers.
-
- r set a relocation register
-
- r 'n' set relocation register 1 to 'n'
- r 'd' 'n' set relocation register 'd' to 'n'
- r * 'n' set all relocation registers to 'n'
- r * note that 'n' is zero by default so that
- r* will set all relocation registers to
- zero. Initially all are zero anyway.
-
- x exit
-
- x leaves MUD and halts. This instruction would only
- be used when running under a monitor operating system.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 26
-
- cont.
-
-
- s spy on store
-
- s 'l' spy on the store starting at location 'l'.
- The address is displayed followed by the
- contents. The contents can be changed by
- typing a number followed by <return>, in
- which case the new value will be displayed.
- To advance to the next location just type
- space, to retreat to the previous location
- type tab. To finish the spy type <return>.
- Note that typing <return> with no number
- does not change the value in store.
-
- eg
- mud> r100
- mud> s20.
- 000120> 123456 23
- 000120> 000023 000122> 077177
- mud>
-
- this leaves location 122 unchanged, but puts
- 23 into location 120.
-
- s 'l1' 'l2'
- spys on locations 'l1' to 'l2', but does
- not allow you to change any values.
- Effectively this is just a display or dump
- command. 'l1' should be less than or equal
- to 'l2' or nothing will happen. To stop
- the printing hit <escape>. This is handy if
- you specify an enormous amount of printing
- by mistake.
-
- sr spy on registers
-
- sr spys starting at register 0
- sr 'd' spys starting at register 'd'
- This is similar to spy on store, but you can
- only progress forward one register at a
- time, by typing <space>. After reaching
- register 7, the program counter, you get to
- look at the psw. The only way to spy on the
- psw is to first spy on register 7. If you
- space forward from the psw you get back to
- register 0, to get out of the spy type
- <return>.
-
-
-
-
-
-
-
-
- 27
-
- cont.
-
-
- sw spy on the window
-
- sw spy on the memory management registers. At present
- you are restricted to looking at the registers for
- the pages allocated to processes, which under EMMOS
- should be the only ones to change.
- The registers are automatically split into their
- composite fields for displaying
- and changing. To go forward to the next field, type
- <space>, to go to the next page, type <tab> and to
- exit type <return>. Numeric fields are changed by
- typing a number followed by <return>, other fields
- are changed by typing one character.
- the expansion direction, ed> is either up=u or down=d
- the access control is either non resident = n
- read only = r
- or read/write = w
- an access control of 'unused' indicated an error
- in the memory management registers. The written into
- bit cannot be examined or changed.
-
- b set a breakpoint
-
- b 'l' puts a breakpoint at location 'l'. Note
- that you are not allowed to place a breakpoint
- on top of another breakpoint. It
- is possible to set breakpoints on top of emt
- instructions, but, once they have been
- reached, it is not possible to
- continue or single step from them.
-
- k kill a breakpoint
-
- k 'l' kills the breakpoint at location 'l'. If
- the program is halted at the breakpoint, it
- is not possible to continue from there, use
- 'go' instead.
- k * kills all breakpoints. If the program had
- halted at a breakpoint it will not be
- possible to continue, use 'go' instead.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 28
-
- cont.
-
-
- g go to command
-
- g 'l' jumps to location 'l' and starts
- executing. 'l' must be a virtual address,
- mapped according to the window. The
- registers are loaded as set.
- gs 'l' as above, but single stepping. Only one
- instruction is executed before control is
- returned to MUD. When single stepping all
- breakpoints are temporarily removed, so no
- breakpoints as such will be hit.
-
- c continue command
-
- c continue from the breakpoint last reached or at the
- next instruction if previously single stepping.
- cs as for continue but single stepping
- ( see 'gs' above )
-
- Note that it is not possible to continue from a
- breakpoint that has just been killed, but you can
- use 'g' instead with 'l' as the contents of the program
- counter, R7.
-
- i change I/O command
-
- This command has a special syntax, because it is
- used to redirect the input and output of MUD from one
- terminal to another.
-
- i change I/O to the console
- iv 'n' change I/O to vdu 'n'
- is sink the output. All output will be thrown away,
- including echoing. Input remains on the same channel.
-
- f find a value
-
- f 'v' searches the physical memory, stating at
- location zero, for a word containing the value
- 'v'. Every so often a message will say
- "still looking" if one has'nt been found
- yet. To stop the search early hit <escape>
- to break in.
- f 'v' 'l'
- As above but the search starts at 'l'
- instead of zero.
-
-
-
-
-
-
-
-
- 29
-
- cont.
-
-
- e evaluate an expression
-
- This command evaluates an 18 bit expession, using octal
- or decimal numbers or the contents of a relocation register. There
- is one accumulator, acc, which holds an 18 bit number. The operations
- that can be performed on it are:
-
- ^ val Load the acc with 'val'
- + val Add 'val' into the acc
- - val Subtract 'val' from the acc
- P Convert the least significant 16 bits of acc into an
- 18 bit virtual address
- V Treat the value in acc as an 18 bit physical address and
- convert it into a 16 bit virtual address.
-
- The values are given by:
-
- # octal number - an 18 bit octal number, the # can be omitted
- $ decimal number- a 15 bit decimal number, ie positive only
- R num - the 18 bit value of relocation register 'num',
- num is 1 by default
-
- Several commands can appear on one line, seperated by commas
- or spaces if it is necessary to avoid ambiguity. The value in acc is
- displayed when the end of the line is reached.
-
- The value in acc is zero the first time the 'e' command is
- used. Subsequently the value is that left in it after the last use
- of 'e'.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 30
-
- 2.2.6 Using MUD
-
- If RESMUD is linked in before EMMPM and MUD is present as an
- overlay, then the debugger will be entered once the system has been
- loaded. If not the debugger cannot be used.
-
- When control is passed from MUD to the user program, by using the
- go or continue commands, the system error traps are set so that any
- error will be handled by MUD. This remains so until the user program
- changes them. Note that while MUD is running the traps are set to
- different handlers which detect whether the debugger itself is in error.
- If so check that RESMUD has been assembled with the current page
- configuration.
-
- We can return to the debugger at any time via the console emulator.
- Find the address of the global symbol $MUDIN, it is part of RESMUD and
- so is permanently resident, it's virtual and physical address is
- therefore the same. Use the console emulator to jump to this location
- and MUD will restart.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 31
-
- 2.3 Linker and Loader Functions
- ___________________________________
-
- In general a system's linker and loader perform two logically
- distinct functions, though in practice the border between these
- functions may be less clear. In a virtual memory system it is usually
- the operating system that allocates physical memory, but in a monitor
- system this may be done by the linker. There are a number of functions
- that the linker and loader are required to perform on an EMMOS system.
- Some of these functions require a degree of intelligence that is not
- usually found in either linkers or loaders. These intelligent functions
- may be incorporated in either the linker or the loader, or distributed
- between them. When presenting these functions we will describe them all
- as being part of the linker, for ease of understanding. The loader then,
- just copies an output image file from the linker, word for word into the
- 128K physical memory. However, linkers are complex pieces of system
- software, that are difficult to write or modify. Therefore, in practice,
- one usually takes the best of the functions that the linker has to offer
- and writes a loader program which incorporates those remaining.The
- functions that the linker/loader must perform are listed below:
-
- 1. Resolve all global references and relocate the
- object code.
- 2. Allocate physical memory for the system, buffers,
- process code and stacks. This takes into account
- the page configuration scheme.
- 3. Construct a Load Map which specifies where processes
- are in physical memory and where the ends of their
- stacks are in virtual memory. This is passed on to the
- loaded system.
-
- 2.3.1 The Linker
-
- We can consider the input to the linker to be a set of Relocatable
- Binary ( RLB ) modules, with some system of reference resolving that
- need not concern us. A process' body is made up of one or more RLB
- modules, with sharing allowed. EMMOS is similarly composed. To specify
- how the system and process bodies are constructed we supply the linker
- with a Link Control File, which specifies which modules make up the
- system and process bodies, and the order in which they are to be linked
- to form the body. We also need a way of uniquely identifying a process
- body, so that when we create a process we can specify which code body to
- use.
-
- Here we give an example of what this file could look like. The line
- headed 'SYSTEM' would define the construction of the resident operating
- system part of EMMOS and lines headed 'BODY' would each describe a
- process body, it's name given in brackets:
-
- SYSTEM: EMMPM-EMMTTY-..........-EMMMEM;
- BODY(X25): X25CODE;
- BODY(PRINTR): IOCODE-IOLIB;
- END:
-
-
-
-
- 32
-
- cont.
-
- The EMMOS linker must also allocate physical memory for the process
- code bodies and stacks. In order to do this it needs to know which code
- bodies will be incarnated as which processes and how much stack to give
- those processes.T This information could go in the Link Control File. As
- an example of how it could be represented, we consider the example body
- description given above, and create some processes with those bodies:
-
- PROC(X25-A): "X25" ,SYSTEM=200
- PROC(X25-B): "X25" ,SYSTEM=200
- PROC(PRINTR): "PRINTR",SYSTEM=100,CORAL=400
- END:
-
- Here we describe three processes, called X25-A, X25-B and PRINTR.
- The first two are both incarnations of the body "X25" and both have 200
- words for their system stack and no CORAL stack. It's not necessary for
- them to have the same size stacks, though some implementations could
- impose this as a restriction with no great hardship. The third process,
- "PRINTR", is the one and only incarnation of the body "PRINTR". It has
- 100 words for it's system stack and 400 words for it's CORAL stack.
-
- The linker still requires information on the page configuration
- before it can allocate physical memory. This information is not strictly
- necessary. We could allocate the code and stacks for each process as one
- lump of physical store and if it is too large for the configuration,
- then the system will fail at run time. By knowing the page allocation
- scheme however, the linker can be quite subtle and avoid unnecessary
- duplication of code and could even arrange for the code and stacks to be
- on separate pages if the sizes are right. ( For more details see 3.2.7/8
- ). To complete our example we shall give an idea of how the
- configuration could be specified in the Link Control File:
-
- PROCS 5..6, BUFFERS 0..2, EMMOS 3..4;
-
- Note that page 7 must always be allocated for the I/O page and that
- the section using page 0 will lose the first 1000 octal bytes for the
- vector area.
-
- In our example, if the body "X25" was less than 4K words then it
- would fit on one memory page. Since the stacks for "X25-A" and "X25-B"
- are quite small, they too fit on one page. The linker should then only
- put one copy of the body into physical memory and arrange the mapping of
- both the processes such that page 5 maps onto it. Page 6 would map onto
- the processes stack areas, which would of course be different physical
- memory locations.
-
- Once the linker has finished allocating physical memory it needs to
- be able to tell the EMMOS initializer what the memory management window
- for each process is and where it's stacks are. It does this by including
- a table with this information in, in the Load Image File. This table
- must be loaded at a place in memory where the initializer can find it,
- say somewhere in the global buffer pool.
-
-
-
-
- 33
-
- 2.3.2 The Loader
-
- The Loader takes the Load Image file as input. This file is
- produced by the linker and contains absolute binary data with an
- indication of where in physical memory to load it. The loader need not
- know anything about the processes or the system it is loading. However
- there needs to be some way of telling where the system's entry point is.
- Note that since the entry point will be a virtual address it is
- necessary to include an initial memory mapping as part of it's
- definition.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 34
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- PART THREE
- __________
-
- HOST MACHINE ASPECTS
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 35
-
- 3.1 Linking Using the RSX Task Builder
- ___________________________________________
-
- The RSX task builder( TKB ) is used as the linker. It is because
- not all the functions we require are supplied by this linker, that our
- loader is more complicated then usual. The Task Builder is used to
- perform the relocating and global reference resolving parts of the
- required actions. The physical memory allocation, process incarnation
- and the production of the Load Map are all actions that are performed by
- our loader. This does mean that the loader is complicated, but less
- overall effort is required to write it than to completely re-write the
- linker.
-
- 3.1.1 Use of the Task Builder
-
- The task builder is able to handle overlays in several ways. It can
- produce disk resident overlays, in which "paged-out" segments reside on
- disk, or memory resident overlays, in which all segments reside in
- physical memory but not all are "paged-in" into virtual memory. TKB will
- also allow your task to be some combination of the two. Overlays are
- paged in and out by special calls to RSX which TKB automatically inserts
- into the object code. It is possible to instruct TKB to leave out this
- code, allowing the user to handle his own paging. Overlays are
- characterized by being relocated at the same place in memory. it is this
- feature that EMMOS exploits to get all the process' bodies relocated at
- the same base address. We do however require that the linker does not
- put any auto loading code in for the overlays.
-
- Amongst the various tables hidden in the task image, is the window
- description table, this does not appear for disk resident overlays, so
- we chose to use memory resident overlays throughout. Also, when using
- memory resident overlays, each layer of the overlay tree is relocated on
- a page boundary, which is another requirement for EMMOS. There is an
- option, when running a task under RSX, of allowing it to be swapped in
- and out of physical memory ( checkpointed ). A checkpointable task has a
- large space in it's task image file, so as EMMOS has no need of it, the
- task must be built not checkpointable ( /-CP switch ). We will assume
- then that the task is not checkpointable, with manually loaded ( though
- we shall not include the calls to do it ) memory resident overlays.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 36
-
- The first snag is met when we try to get information about the size
- of the overlays and their position within the task image. The tables
- that contain this information follow on directly after the code of the
- root segment, but there is no indication as to how long the root is,
- except in these tables. Normally their position is known because the
- overlay loading mechanism references them, but we've done away with
- this. Ideally the root segment would be the EMMOS system, but there is
- no clean way of finding out how long it is, so we chose to not allocate
- page 0 to the system. Instead the root segment does not contain any
- code, only some tables of known length used by the loader.
- Unfortunately, because TKB will relocate the next overlay layer on page
- 1, we have used up 4K of virtual space just for the interrupt vectors
- etc. To avoid this we allocate the global buffer pool space to pages
- 0,1.... because no code is loaded for it. The problem remains to
- persuade TKB to relocate EMMOS at the end of the buffers. We could do
- this by extending the root segment to occupy all these pages and then
- just ignore it all when loading, but this would mean the task image file
- would be enormous. Instead we use dummy overlay layers. Although each
- layer contains only one word, it is sufficient to persuade TKB to
- relocate the next layer at the next page boundary.
-
- It is because of such devious means of getting the overlay
- relocated to the desired base, that all the calculations performed by
- TKB to produce physical memory load addresses are useless. Instead of
- wasting large areas of physical memory the loader does the calculations
- again. This also means that we can handle the process' stacks nicely.
-
- Finally there is the problem of uniquely identifying each overlay,
- so a process can specify which is to be it's code body. TKB gives each
- overlay a name, which is the first six characters of the first object
- file's name in the overlay, however this may not be unique. We have then
- two options; use the name given by TKB or use a position numbering
- scheme. Despite it's drawbacks of non-uniqueness, the former was chosen.
- Names are easier to understand then numbers, and the possible inclusion
- of the debugger may well upset the numbering, though it is a special
- case. The use of six character names for the overlays led us to adopt
- the <name> field of the $CREAP macro to specify which code body to use.
- Other schemes may require another field in the macro call.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 37
-
- 3.1.2 The Format of the Task Image File
-
- The information required to complete the Overlay Description Table
- is scattered across the first few blocks of the task image file. The
- format is dependant on various switches and the form of the ODL file.
- There follows a brief description of the parts relevant to the loader,
- assuming it was built in the required manner.
-
-
- BLOCK 0:
-
- Contains no useful information, except perhaps the creation
- date of the task image.
-
- BLOCK 1:
-
- No useful information.
-
- BLOCK 2:
-
- This is the start of the task header. The word at byte
- offset 72 octal is the "header guard word pointer". This
- contains the byte offset, within the next block, of the "guard
- word", this immediatly preceeds the code of the root segment and
- is how the loader finds the root.
-
- BLOCK 3:
-
- This contains the start of the root segment. The first word
- of the root follows the "guard word". The root segment is used
- to transmit configuration details and the process description
- table to the loader. Immediatly following these tables is 29
- words of rubbish ( code used to load the overlays under RSX ),
- the segment descriptor table, one word of rubbish and then the
- window descriptor table. These two tables are used by RSX to
- define the positions of the memory resident overlays in physical
- memory, EMMOS uses them to construct the Overlay Description
- Table, as follows:
-
- segment descriptor table -
- each entry is 9 words long, there is one entry for each overlay and
- the root
- word offset 1 the virtual base address
- word offset 6&7 the segment's name in radix 50 format.
-
- window descriptor table -
- each entry is 10 words long, there is one entry for each overlay
- word offset 2 overlay's size in memory blocks (64bytes)
-
-
- NEXT BLOCK BOUNDARY:
-
- The code of the first overlay begins at the first word of
- the next disk block. Subsequent overlays start on block
- boundaries following on in order.
-
-
- 38
-
- 3.1.3 The Overlay Description Language
-
- The Task Builder takes a series of object files and links them
- together to produce a Task Image. This is the exact image of what is to
- be loaded at run time ( under RSX ). EMMOS exploits the memory resident
- overlay capabilities of the Task Builder in order to relocate the system
- kernel and processes' bodies in the desired place. The arrangement of
- the overlays is described in the Overlay Description Language ( ODL )
- file, the structure of which is as follows:
-
- module1 - module2 - ............ - moduleN
-
- specifies that the N modules are to be concatenated in the given
- order
-
- ( module1, module2, ............ , moduleN )
-
- specifies that the N modules will overlay each other in virtual
- memory. The modules not paged-in will be resident on disk or, if they
- are memory resident overlays ( indicated by a ! before the open bracket
- ), in physical memory.
-
- These concatenation and overlay operations are combined to describe
- the overlay tree structure, eg:
-
- A - B - !( C - D - !( E , F ) , G - !( H - !( I , J ) , K ) , L )
- this specifies the following tree
- E F I J
- |___| |___|
- D H K
- | |_____|
- C G L
- |___________|__________|
- B
- |
- A
-
- At any one time during runtime, the memory will contain those
- modules lying on one of the paths from the root to a leaf.
-
- For ease of writing, it is possible to give parts of the overlay
- tree a name, using the factor command ( .FCTR ). so a complete ODL file
- for the above example could be:
-
- .ROOT A - B - !( OV1 , OV2 , L )
- OV1: .FCTR C - D - OV11
- OV2: .FCTR G - !( OV22 , K )
- OV11: .FCTR !( E , F )
- OV22: .FCTR H - !( I , J )
- .END
-
-
-
-
-
-
-
- 39
-
- 3.1.4 The EMMOS ODL File
-
-
- .ROOT ROOT - !( OV1 - !( OV2 - !( EMMOS - !( PROCS ) ) ) )
- EMMOS: .FCTR EMMPM - FIRST - ......................
- PROCS: .FCTR BODY1 , BODY2 , ..............., BODYn
-
- The factor EMMOS describes all the system modules, which are all
- concatenated. The factor PROCS describes each of the different code
- bodies for the processes. Normally only one code body is required at a
- time so the modules overlay each other, but it is possible to
- concatenate processes which are to access common routines.
-
- For example, suppose we have four code bodies BODY1, ... , BODY4
- which are each $CREAPed only once to give processes PROC1, ... , PROC4.
- If these processes are completely independant then we write:
-
- PROCS: .FCTR BODY1 , BODY2 , BODY3 , BODY4
-
- Suppose we have a library module, LIB, that is shared by PROC1 and
- PROC2, then we could write:
-
- PROCS: .FCTR BODY1 - LIB , BODY2 - LIB , BODY3 , BODY4
-
- This would cause two copies of LIB to be in physical memory. We
- could however write:
-
- PROCS: .FCTR BODY1 - BODY2 - LIB , BODY3 , BODY4
-
- which would cause one copy of LIB to be put in the task image, but
- PROC1 and PROC2 would now be paged in and out of virtual memory
- together, which may not be desirable.
-
- Note that if the total size of BODY1, BODY2, LIB and the stacks for
- PROC1 and PROC2 exceeds the space allocated to processes, then the
- loader will duplicate some or all of the code in an attempt to fit it
- in. It may be then, that more physical memory would be used in trying to
- share LIB than if we specified duplication in the first place.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 40
-
- cont.
-
- The modules ROOT, OV1, OV2, ..... OVn are required by the system to
- ensure that the operating system and the process bodies are relocated in
- the correct place. ROOT also transmits information from the $CREAP macro
- calls to the loader. The Task Builder relocates the first "layer" of the
- overlay tree ( the root ) at location zero. Successsive layers are
- relocated at the start of the next page boundary ( a page is 4K words
- long ). So, because each of these modules is quite small, ROOT is
- relocated at 0, OV1 at 20000, OV2 at 40000 etc. If we require the
- operating system to be relocated at 60000, we put it in the next layer (
- as in the above example ). Suppose we want EMMOS to start on page 4 (
- location 100000 ), and it is over one page long so the processes will be
- on page 6 ( location 140000 ), we would need to pack out pages 0..3 thus
-
- .ROOT ROOT - !( OV1 - !( OV2 - !( OV3 - !( EMMOS - !( PROCS ) ) ) ) )
-
- For technical reasons it was not possible to have the operating
- system at the low numbered end of memory, so that is where the buffers
- have been put. Dummy overlays are used to pad out the buffer area
- because they cause the task image to be much smaller than if we had a
- .BLKW . The latter would cause it to contain about 12K of zeroes!
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 41
-
- 3.1.5 Installation of the Debugger
-
- The EMMOS debugger, MUD, is in two parts, a resident part RESMUD
- and an overlay part MUD. To be able to use the debugger both parts must
- be included in the ODL file. RESMUD must appear before EMMOS but MUD can
- be put anywhere amongst the PROCS, eg:
-
- .ROOT ROOT - !( OV1 - !( OV2 - !( RESMUD - EMMOS - !( PROCS , MUD ) ) ) )
-
- 3.1.6 Creating the Task Image File
-
- Once the form of the ODL file has been worked out the task builder
- is run under RSX-11 by:
-
- TKB EMMOS , EMMOS /NOSP = EMMOS /MP
-
- The first output file is for the Task Image ( .TSK ) file, the
- second is the task map ( .MAP ) file, which is spooled by default. The
- MP switch specifies that the input file is an .ODL file.
-
- The .MAP shows the structure of the task image and gives the
- virtual addresses of the modules, global symbols and .PSECTs. This link
- map should be used in conjunction with the loader's load map, which
- specifies physical addresses of code and stacks, when debugging. The
- .TSK file now needs to be copied to the RT-11 format disk which contains
- the loader using FLX. The system is now ready for loading and running.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 42
-
- 3.2 The EMMOS RSX Task Image Loader
- _______________________________________
-
- This section describes the operation of the loader for the Extended
- Memory MOS system. The loader itself is loaded from a floppy disk in
- RT-11 format, using a fairly standard bootstrap loader. The EMMOS loader
- then loads the system from an RSX-11 Task Builder Image file ( stored in
- RT-11 format ) on the same floppy disk. Control is then passed to the
- operating system or to the EMMOS debugger, MUD, if it is loaded.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 43
-
- 3.2.1 Inputs and Outputs
-
- The input to the loader is an RSX-11 Task Builder Image file stored
- on a floppy disk in RT-11 format. This file contains:
-
- 1. The Configuration Table ( see 3.2.3 )
- 2. The Overlay Description Table ( see 3.2.4 )
- 3. The Process Description Table ( see 3.2.5 )
- 4. Absolute binary code for the operating system
- and processes.
-
- The loader produces a table, the load map, which it places in
- memory and displays on the console, that describes the positioning of
- all the processes in physical memory.
-
- The address of the entry point to the loaded system must be stored
- in the first word of the system. This is set by MOSPM or, if the
- debugger is included, RESMUD.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 44
-
- 3.2.2 The Console Load Map
-
- This is a human readable form of the LOAD MAP that is supplied to
- the loaded system. There is one line for each process describing the
- position of it's code and stacks.
-
- The first column gives the process id ( pid ), the next two the
- limits of the code and the fourth the limits of the two stacks combined.
-
- If none of the pages containing code, contain any stack then the
- third column will read "unshared", that is, there is no page that
- contains both stack and code. However, if there is only one page for
- processes then this must contain all the code and all the stack, in this
- case the third column will read "page is shared".
-
- If the code is longer than one page, and it is necessary to have a
- page containing both stack and code, then the third column will be the
- limits of the piece of code that is sharing with the stacks. This may be
- a copied piece of code.
-
- The limits are given in terms of physical memory blocks, so a limit
- of
-
- 001200 - 001250
-
- for the code would mean that the code starts at physical memory
- location 120000 and ends somewhere between 125000 and 125077.
-
- If the task image does not contain an overlay for a process' body,
- then the load map entry for that process will be of the form:
-
- pid - ABCDEF has'nt got a body
-
- If one or more processes lack bodies then the load will be
- abandoned, once the load map has been printed, with the message:
-
- "process requires body" (see ERRORS)
-
- Note: the printing of the Load Map can be abandoned by hitting
- <escape>.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 45
-
- 3.2.3 The Configuration Table
-
- This table resides in the root segment of the task image,
- immediately before the Process Description Table. It is used to tell the
- loader the page allocation scheme and the maximum number of processes.
- The information is passed to it at run time so that the loader need not
- be re-compiled for every change in the configuration.
-
- The format is:
-
- VAR config_table :RECORD
- max_number_of_processes,
- load_map_address,
- first_mos_page, last_mos_page,
- first_process_page, last_process_page
- : INTEGER
- END;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 46
-
- 3.2.4 The Overlay Description Table
-
- This table is constructed by the loader from the task image's
- window and segment descriptor tables, that follow the root segment. Each
- overlay named by the task image ( except the dummy ones and MOS ) has an
- entry of the form:
-
- TYPE overlay_description = RECORD
- name : ascii;
- size : mem_blocks;
- disk_address : INTEGER
- END;
-
- TYPE ascii = ARRAY[ 1:6 ] OF CHAR;
-
- TYPE mem_blocks = 0..number_of_process_pages * #200 -1;
-
- The table is given by
-
- odt : ARRAY[ 1..number_of_overlays ] OF overlay_description;
-
-
- odt[ ov ].size contains the size of the overlay segment ( that is of
- the code ) in 32 word memory blocks.
- odt[ ov ].name is the overlay's name, taken from the overlay description
- language file at build time.
- odt[ ov ].disk_address is the number of the disk block where the overlay starts.
-
- Note that the disk address field is not used in the current version
- of the loader. It remains as a left-over from a version that would not
- support down line loading.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 47
-
- 3.2.5 The Process Description Table
-
- This table resides in the root segment of the task image, following
- the Configuration Table. It is produced by the $CREAPs used to create
- the processes. It is used to tell the loader which processes are
- required, which overlay will supply the code and the size of their
- stacks. There is one entry in the table per process, each of the form:
-
- TYPE process_description = RECORD
- pid : INTEGER;
- name : ascii;
- r0_size, r6_size : mem_blocks
- END;
-
- TYPE ascii = ARRAY [ 1..6 ] OF CHAR;
-
- TYPE mem_blocks = 0..number_of_process_pages * #200 - 1;
-
- The table is given by
-
- VAR pdt : ARRAY [ 1..number_of_processes ] OF process_description;
-
-
- pdt[ i ] is the entry for the ith process,
- so pdt[ i ].pid = i for all i IN 1..number_of_processes.
- The name field contains the six character name of the overlay which is the
- code for the process. This is taken from the second parameter of the $CREAP
- macro call.
- pdt[ i ].r0_size and pdt[ i ].r6_size contain the required sizes, in 32
- word memory blocks, of the stacks.
- Note that the macro converts the sizes from words to memory blocks before
- placing the values in the table, using
- size_in_blocks := ceiling( size_in_words / 32 ).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 48
-
- 3.2.6 The Load Map
-
- The load map describes the loaded system to the initializer. It is
- placed in memory by the loader at an agreed address before it gives
- control to the system. There is one entry in the table for each process,
- and a special one for the debugger if it is included in the task image.
- The form of a table entry is:
-
- TYPE load_description = RECORD
- pid,
- r0_low, r0_hi,
- r6_low, r6_hi : INTEGER;
- window : ARRAY
- [ first_page..last_page ]
- OF window_type
- END;
-
- TYPE window_type = RECORD par, pdr : INTEGER END;
-
- The map is given by:
-
- map : ARRAY [ 1..number_of_processes + 1 ] OF load_description
-
-
- map[i] is the entry for the ith process, so map[i].pid = i, for all
- i IN 1..number_of_processes. map[i].pid = -1 for the debugger entry. Any
- unused entries have pid = 0.
-
- r0_low and r0_hi contain the virtual byte addresses of the lowest
- and highest numbered words in the R0 ( CORAL ) stack for the process.
- Similarly for r6_low, r6_hi.
-
- window describes the mapping from virtual memory onto this process.
- There are two words for each page allocated to a process, the page
- address register and the page descriptor register.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 49
-
- 3.2.7 The Physical Memory Allocation Algorithm
-
- The loader should attempt to arrange the loading of the Load Image
- into physical memory in a way that will reduce the amount of physical
- memory required. The total amount of virtual memory allocated to a
- process for it's code body and stacks will be fixed ( = num_pp memory
- pages ), but for each process the sizes of it's code and the total size
- of it's two stacks will vary.
-
- If at all possible the loader will arrange for the stacks and the
- code to be on different pages in virtual memory, allowing the process to
- put read-only protection on it's code. This is only possible if:
-
- pages( code_size ) + pages( stack_size ) <= num_pp
-
- where pages( i ) = the size i rounded up into a whole number of
- memory pages. Of course if pages( code_size + stack_size ) > num_pp then
- not enough virtual memory is availiable for this process. However if we
- have:
-
- pages( code_size + stack_size ) = num_pp
-
- then some of the code and some of the stack space must share one of
- the pages. The shared page cannot then have read-only protection placed
- on it. If a process has already been created with this code body then
- physical memory following the code body will have been allocated as a
- stack. We cannot then have the stack for the next process following
- directly on from the code, so it may be necessary to copy part of the
- code body and arrange that the memory mapping maps the two parts of the
- code onto consecutive virtual memory locations.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 50
-
- E.G.
-
- Suppose we have two pages for a process, num_pp = 2, and we have a
- code body which is $CREAPed twice, as PROC1 with stacks S1 and as PROC2
- with stacks S2. If the code body is larger than one page then the second
- page must be shared between the stacks and some of the code.
-
- First the loader copies the code body into physical memory, then it
- allocates the stacks for PROC1, the window for PROC1 will be
- (a..b,b..d).
-
- --a---------------b----c------d----f---------------
- : code size : S1 : ....physical memory
- ---------------------------------------------------
- |<- 4K words -->|<-- 4K words -->|
-
- Now for PROC2. If pages( code size + S1 + S2 ) <= num_pp, then the
- loader can allocate the stack following on directly from S1, thus the
- window for PROC2 will be (a..b,b..e).
-
- ---a--------------b----c------d--e-f---------------
- : code size : S1 :S2:
- ---------------------------------------------------
-
- Note that PROC2's window allows it to ( illegally ) access the
- stack of S1. If however pages( code size + S1 + S2 ) > num_pp then the
- loader must take a copy of the piece of code that overlaps the second
- page, (copy from b..c to d..g), thus the window for PROC2 will be (
- a..b,d..h ), and the copy will be mapped into the same virtual locations
- as the original.
-
- ---a--------------b----c------d--e-fg--h------------
- : code size : S1 :copy :S2:
- ----------------------------------------------------
-
- Now PROC1's stack is not in the window of PROC2 so neither process
- can use the other's stack.
-
- The loader will try and fit as many stacks as possible into the
- page without copying a piece of code, but it wont try to optimize the
- ordering. If the code size is smaller than a page and the stacks are
- bigger then the whole of the code will be copied.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 51
-
- 3.2.8 The Logical Operation of the Loader
-
-
- get process description table from task image;
- construct overlay description table;
- load EMMOS;
- FOR each overlay
- DO
- load the code;
- FOR each process
- DO
- IF name of process = name of overlay
- THEN
- IF size of code in pages + size of stacks in pages
- <= number of pages for processes
- THEN
- code and stacks are on completely different pages;
- set up the window for the process;
- leave room for the stacks in physical memory
-
- ELSF (size of code + stacks) in pages
- = number of pages for processes
- THEN
- one page contains stack and code;
- IF stack will fit on the end of the last
- incarnation's window
- THEN
- leave room for the stacks after last stack;
- set up the process' window
- ELSE
- make a copy of the piece of code that must
- share a page with some stack;
- leave room for the stacks after the copied code;
- set up the window for the process
- FI
- ELSE
- process is too large
- FI
- FI
- OD
- OD
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 52
-
- 3.2.9 Error Messages
-
- i. System Traps
-
- These indicate something has gone drastically wrong with
- the loader, hopefully they will only occur after modifications
- have been made and not thoroughly tested. They may also occur if
- the loaded system goes wrong before it has set the trap
- locations to its own trap handlers.
-
- cpu error: pc = nnnnnn ps = mmmmmm
- reserved instruction: pc = nnnnnn ps = mmmmmm
-
- These messages occur when a trap to #004 and #010 occur.
- The contents of the program counter and processor staus word, as
- placed on the stack by the trap, are displayed.
-
-
- memory management trap 250
- nnnnnn at mmmmmm
-
- This message occurs when something goes wrong with the
- memory management. The contents of the two status registers are
- displayed. nnnnnn = SR0 which is further expanded in full
- following the error message , and mmmmmm = SR2, the virtual
- address associated with the error. Following the written
- expansion of SR0, the contents of the kernel mode memory
- management registers are displayed.
-
-
- power failed, start again
-
- the power to the processor failed, re-boot the system. NB
- this has not been tested!!!!
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 53
-
- ii. Loader Errors and Messages
-
-
- test: eof
-
- The end of the task builder image file has been reached prematurely.
-
- test: get has failed
-
- An error occurred in the transfer of data from the floppy disk. Try
- again.
-
- test: rewind
-
- The loader requires the input task image file to be rewound. This
- is only an error if the file is not on a rewindable device, eg down
- line loading. It is caused by an error in the loader.
-
- cant find 'task file name'
-
- The file is not on the floppy disk, check the file name specified
- in the loader is the same as you copied to the disk, and the disk
- is in the correct drive ( drive 0 ). Remember that the name specified
- in the loader must include any blanks necessary to pack the name to
- 10 chars, in the form ABCDEF.EXT
-
- too short!
-
- The file is less than 4 blocks long, so cannot possibly be the
- correct task image.
-
- first dummy overlay not found
-
- the dummy overlay that is used to pack out the buffer area is not
- present in the task image. Check the file is a task image and that
- the ODL file correctly specifies the dummy overlays.
-
- mos is larger than nn pages long
-
- the resident part of EMMOS is too large, more than the nn pages
- specified in the configuration file. Make sure that the processes
- have been put in as overlays and not in the resident part.
-
- window and segment descriptors of unequal size
-
- The loader has lost it's place in the task image, or the ODL file
- does not specify the overlays in the correct format.
-
- ABCDEF is too large
-
- The named overlay is too large for the configuration, even without
- stacks. Check that the overlay names are seperated by commas in the ODL
- file.
-
-
-
-
- 54
-
- Errors and Messages - cont.
-
-
-
- process nn too large
-
- The process with pid = nn has stack and code too large for the
- configuration. Check that stack sizes have been given in words in
- the $CREAP macro call.
-
- ABCDEF has'nt been made a process
-
- The named overlay does'nt appear in any of the $CREAPs. The overlay
- is loaded but otherwise ignored, this is not a fatal error.
-
- process nn: code duplicated
-
- The loader was forced to make a copy of some of the process' code
- because the code had already been $CREAPed and the stack and code
- needs to share a page. This is not an error.
-
- debugger has been loaded nnnnnn - mmmmmm
-
- The overlay part of the debugger has been loaded, starting at
- memory block nnnnnn and finishing in block mmmmmm. This is not an
- error.
-
- ABCDEF has incorrect base address = nnnnnn
-
- The named overlay has been relocated at nnnnnn by the Task Builder.
- This does not agree with the virtual page allocation scheme given.
- Check that the ODL file is correct, that the right number of dummy
- packing overlays are present and that all overlays are not too
- large for the configuration.
-
- debugger is too large
-
- The debugger takes up more space than is allowed for processes. it
- is still loaded into physical memory, but only those pages normally
- allowed for processes will be paged into virtual memory, this will
- almost certainly cause MUD to crash. Use the console emulator to
- enter the system instead of MUD. Alternatively, remove the debugger
- or allow more pages for processes. This is not a fatal error.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 55
-
- Errors and Messages - cont.
-
-
-
-
- the debugger cannot be used
-
- Either the resident part or the overlay part of the debugger are
- missing and hence the debugger cannot be used. If the debugger is
- needed then include the missing name in the ODL file. This is not a
- fatal error.
-
- non-unique overlay ABCDEF
-
- The ODL file describes a configuration such that two overlays have
- the same name. The loader requires all overlays to have unique
- names so it can unambiguously select the code body for a process.
- Try re-ordering the overlay description in the ODL file. If the
- effending overlay is a common library, put it's name after the code
- body, otherwise the file may need to be copied to one of a
- different name.
-
- process requires body
-
- at least one process has specified a body name that does not
- appear in the Task Image as an overlay. An indication of which
- process is causing the problem can be found from the Console Load
- Map (qv). Make sure the name specified in the $CREAP macro call
- is that of one of the object files, check in the task map for
- the names actually used. If the debugger is included, make sure
- it, and all other overlays, are separated by commas in the ODL
- file.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 56
-
- 3.2.10 Tracing
-
- The loader and it's libraries are liberally scattered with code to
- produce vast amounts of output, that describes in detail what is being
- processed. These pieces of code are normally excluded by surrounding
- them in comment brackets. The start of a piece of trace code is
- indicated by {trace and the end is followed by ecart}. To include the
- trace statements change {trace to {trace} and ecart} to {ecart}. This
- will make it easy to restore them later.
-
- The output produced should be self explanatory, except for
- PROCEDURE waiting; which displays the message 'waiting' and waits until
- any character is typed in at the keyboard. All this does is slow down
- the output, since <cntrl-s> and<cntrl-q> are not implemented.
-
- 3.2.11 Changing The System
-
- The loader need not be re-compiled every time the system
- configuration is changed. This is because the configuration information
- is placed in the root segment of the task image file at link time.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 57
-
- 3.3 Process Creation
- ________________________
-
- Processes are created at compile time by calling the $CREAP macro
- in the system configuration module. The $CREAP macro defines the
- attributes of a process; it's entry point, the name of the overlay that
- contains it's code body, the devices associated with it and the size of
- the CORAL and System stacks.
-
- Note, the name given is the name of the overlay in which the code (
- and therefore the entry point ) is found. This name is that of the first
- module given in the overlay subtree. E.g. If we have a library module
- LIB and a process body module BODY1, then in the ODL file we could
- write:
-
- PROCS: .FCTR BODY1 - LIB , .........
- in which case the $CREAP call would be
- $CREAP $ENTRY , <BODY1> , ............
-
- or alternatively
- PROCS .FCTR LIB - BODY1 , .........
- in which case the $CREAP call would need to be
- $CREAP $ENTRY , <LIB > , ...........
-
- For this reason all the overlay names must be unique, othewise the
- loader would not know which code body to give a process. Now suppose we
- have another process body module, BODY2, which also uses LIB. We could
- not write:
-
- PROCS: .FCTR LIB - BODY1 , LIB - BODY2 , .........
- since both overlays would be called LIB. Instead write either
-
- PROCS: .FCTR BODY1 - LIB , BODY2 - LIB , .........
- with
- $CREAP $ENT1 , <BODY1 > , ......
- $CREAP $ENT2 , <BODY2 > , ......
-
- or
- PROCS: .FCTR LIB - BODY1 - BODY2 , ......
- with
- $CREAP $ENT1 , <LIB > , ......
- $CREAP $ENT2 , <LIB > , ......
- or some other combination.
-
- Remember that the name must be of exactly six characters. Pad out
- with blanks if necessary.
-
- The stack sizes are specified using named parameters, these are the
- only extra parameters of $CREAP due to the EMMOS extensions. The sizes
- are given in words, but are automatically rounded up into memory blocks
- ( 32 words ). A zero length R0 stack is acceptable for a non-CORAL
- process, but the R6 stack should always have some space. If the size is
- not specified it is set to 32 words by default. Note the stack sizes are
- given seperately for each process, not for each code body, so two
- incarnations of the same body could have different stack sizes, though
- it would be a bit odd.
-
- 58
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- APPENDICES
- __________
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 59
-
- APPENDIX A Pitfalls.
-
-
-
-
- A.1 Summary
-
- Processes must ensure that all communication is performed via the
- global buffer pool.
-
- Shared overlaid library procedures must not use the CORAL global
- vector for their entry.
-
- CORAL code bodies incarnated more than once should not preset
- variables.
-
- All local variables must be taken from the stack, in code bodies
- incarnated more than once.
-
- All IORBs and their data buffers must be located in permanently
- resident memory (ref 2.1.4).
-
- A.2.1 Use of local space for inter-process communication
-
- Obviously processes with different code bodies cannot use their
- local static space ( ie not the stack ) for communication, but at first
- sight it would appear that different incarnations of the same body could
- communicate using variables in the body. Although sometimes possible,
- this is extremely configuration ( and even loader ) dependant. The
- problem arises when there is not enough room to fit all the code body (
- which includes local static data ) onto process pages of it's own. The
- loader may need to take a copy of some of the code, which may include
- local data. In this case there would be more than one copy of the local
- data, so if two processes use it for communicating, they would actually
- be using two different locations.
-
- Therefore, processes must ensure that all communication is
- performed via the global buffer pool.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 60
-
- A.2.2 Use of shared, overlaid CORAL libraries.
-
- All CORAL procedures, common variables etc., must use unique
- indices to the global vector, to define themselves ( unless some trick
- is being performed ). This remains true even if the procedure is defined
- in an overlay, because there is only one global vector. If a library
- module containing some CORAL procedures only appears in one overlay,
- then the global vector will contain the virtual addresses of the entry
- points. However, the procedures will only be in virtual memory when a
- process which is an incarnation of that overlay is running, so only
- these processes can use the procedures.
-
- This is ok, the problem arises when two or more overlays use the
- library module. If the overlays are such that when relocated, the entry
- points of the procedures are at different virtual locations, the global
- vector mechanism wont work. The entry point recorded will probably be
- that for the last overlay processes by the linker, so the first overlay
- will crash when it tries to call the procedure.
-
- To prevent this all copies of the library module must be relocated
- at the same virtual locations, either by placing it on permanently
- resident EMMOS pages or putting it first in the overlay, though this may
- cause problems with the overlay naming convention. A more satisfactory
- solution in many ways, would be to not use the global vector for the
- procedure entry. The offending procedures would use genuine names for
- their entry points, not vector indices. This is achieved in CORAL by
- using a large index, outside the bounds of the global vector.
-
- A.2.3 Use of static variables
-
- Any data space allocated in a code body, which is incarnated more
- than once, will be used by more than one incarnation, unless the loader
- causes a copy to be made. The processes cannot then use this space for
- private local variables, because another may use the same physical
- memory for it's private local variables. Neither can it be used for
- shared variables, because the loader may have copied them ( see 'use of
- local space for inter process communication' ). Constants are ok since
- all incarnations will require them to remain constant. Beware of string
- constants though, although they really should remain constant, some
- unhealthy procedures actually change some parts of them. Such practices
- should be banned.
-
- In particular, note that the local variables can be created in
- devious ways, in CORAL a preset variable becomes an OWN variable by
- being allocated not on the stack, but in the local static space.
- Presetting and variables in the outermost block must be avoided for
- multi-incarnate processes.
-
- Always take local variables from the stack.
-
-
-
-
-
-
-
-
- 61
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Don't Panic !
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 62
-
-